package me.zhengjie.modules.security.service.impl;

import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.RequiredArgsConstructor;
import me.zhengjie.constant.ThirdConstant;
import me.zhengjie.mapper.UserMapper;
import me.zhengjie.modules.security.config.bean.LoginProperties;
import me.zhengjie.modules.security.config.bean.SecurityProperties;
import me.zhengjie.modules.security.security.TokenProvider;
import me.zhengjie.modules.security.service.IThirdPartyService;
import me.zhengjie.modules.security.service.OnlineUserService;
import me.zhengjie.modules.security.service.dto.JwtUserDto;
import me.zhengjie.pojo.Third.entity.GetTokenDto;
import me.zhengjie.pojo.entity.User;
import me.zhengjie.util.AssertUtils;
import me.zhengjie.util.BaseResponse;
import me.zhengjie.util.ruoyiexcel.StringUtils;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

/**
 * @Description TODO
 * @Author Long
 * @Date 2021/8/25 10:04
 */
@Service
@RequiredArgsConstructor
public class ThirdPartyServiceImpl implements IThirdPartyService {

    private final UserMapper userMapper;
    private final AuthenticationManagerBuilder authenticationManagerBuilder;
    private final TokenProvider tokenProvider;
    private final OnlineUserService onlineUserService;
    private final SecurityProperties properties;
    private final PasswordEncoder passwordEncoder;
    @Resource
    private LoginProperties loginProperties;

    /**
     * 用授权码code获取token，然后获取用户名
     *
     * @param code  重定向得code
     * @param state 状态
     */
    @Override
    public BaseResponse getCode(String code, String state, HttpServletRequest request) throws Exception {
        AssertUtils.isNotNull(code, "登录失败，code不可为空");
        /*根据授权码获取token*/
        HttpRequest post = HttpUtil.createPost(ThirdConstant.GET_TOKEN_URL);
        HashMap<String, Object> map = new HashMap<>();
        map.put("client_id", ThirdConstant.CLIENT_ID);
        map.put("client_secret", ThirdConstant.CLIENT_SECRET);
        map.put("grant_type", ThirdConstant.GRANT_TYPE);
        map.put("redirect_uri", ThirdConstant.REDIRECT_URI);
        map.put("code", code);
        String jsonString = post.form(map).execute().body();
        System.out.println("jsonstring:" + jsonString);
        if (jsonString.contains("error")) return BaseResponse.failed("获取token失败，code错误或已过期");
        GetTokenDto getTokenDto = JSON.parseObject(jsonString, GetTokenDto.class);
        System.out.println("getTokenDto:" + getTokenDto);


        /*根据token获取用户名*/
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("client_id", ThirdConstant.CLIENT_ID);
        jsonObject.put("client_secret", ThirdConstant.CLIENT_SECRET);
        String jsonUser = HttpUtil.post(ThirdConstant.GET_USER_INFO_URL.replace("{token}", getTokenDto.getAccess_token()), jsonObject.toJSONString());
        JSONObject user = JSON.parseObject(jsonUser);
        System.err.println("user_name:" + user.getString("user_name"));
        System.err.println("user:" + user);
        if (StringUtils.isBlank(user.getString("user_name"))) return BaseResponse.failed("用户名为空");


        /*根据用户名和token获取用户详细信息*/
        HttpRequest getDetailUserRequest = HttpUtil.createGet(ThirdConstant.GET_USER_DETAIL_INFO_URL.replace("{loginname}", user.getString("user_name")));
        getDetailUserRequest.header("Authorization", "Bearer " + getTokenDto.getAccess_token());
        String userDetailJson = getDetailUserRequest.execute().body();

        System.err.println("用户详细信息：" + userDetailJson);
        JSONObject result = JSON.parseObject(userDetailJson);
        JSONObject userDetail = result.getJSONObject("data").getJSONArray("content").getJSONObject(0);
        String phone = userDetail.getString("phone");
        String mobile = userDetail.getString("mobile");
        String username = userDetail.getString("username");
        String userType = userDetail.getString("user_type");

        System.err.println("用户phone：" + phone);
        System.err.println("用户mobile：" + mobile);
        System.err.println("用户username：" + username);
        System.err.println("用户userType：" + userType);

        /*根据用户phone、mobile、用户名判断是否在本系统中存在账号*/
        /*如果是教师*/
        /*if (!Objects.equals(ThirdConstant.TEACHER_TYPE, userType)
                || !Objects.equals(ThirdConstant.PART_TIME_JOBTEACHER_TYPE, userType))
            return BaseResponse.failed("该账号并不属于教师");*/
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("third_user_name", username);
        User authUser = userMapper.selectOne(wrapper);
        if (authUser == null) return BaseResponse.failed("你没有本系统的账号，请联系管理员分配");

//        passwordEncoder.encode()
        KwAuthenticationToken authenticationToken =
                new KwAuthenticationToken(authUser.getUserName());
        Authentication authentication = authenticationManagerBuilder.getObject().authenticate(authenticationToken);
        SecurityContextHolder.getContext().setAuthentication(authentication);
        String token = tokenProvider.createToken(authentication);
        final JwtUserDto jwtUserDto = (JwtUserDto) authentication.getPrincipal();
        // 保存在线信息
        onlineUserService.save(jwtUserDto, token, request);
        // 返回 token 与 用户信息
        Map<String, Object> authInfo = new HashMap<String, Object>(2) {{
            put("token", properties.getTokenStartWith() + token);
            put("user", jwtUserDto);
        }};
        if (loginProperties.isSingleLogin()) {
            //踢掉之前已经登录的token
            onlineUserService.checkLoginOnUser(authUser.getUserName(), token);
        }
        return BaseResponse.ok(authInfo);
    }

    /**
     * 获取到微信服务接入返回的code,后获取绑定用户信息
     *
     * @param level
     * @param code
     * @param state
     */
    @Override
    public BaseResponse getWxCode(String level, String code, String state,HttpServletRequest request) {
//TODO 微信服务接入对接
        /*重定向得到的code，去获取用户基本信息*/
//        String s = HttpUtil.get(ThirdConstant.GET_WX_USER_SYS_INFO_URL.replace("{code}", code)
//                .replace("{authenticationCode}", ThirdConstant.AUTHENTICATIONCODE)
//                .replace("{serveName}", ThirdConstant.SERVENAME));
//        System.err.println("微信服务接入返回信息：" + s);
//        JSONObject jsonObject = JSON.parseObject(s);
//        String status = jsonObject.getString("status");
//        if (!Objects.equals(status, "200")) return BaseResponse.failed("获取用户信息错误："+jsonObject.getString("msg"));
//        String data = jsonObject.getString("data");
//        if (StringUtils.isBlank(data)) return BaseResponse.failed("用户信息为空");

        String name="1803011159";
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("third_user_name",name);
        User authUser = userMapper.selectOne(wrapper);
        KwAuthenticationToken authenticationToken =
                new KwAuthenticationToken(authUser.getUserName());
        Authentication authentication = authenticationManagerBuilder.getObject().authenticate(authenticationToken);
        SecurityContextHolder.getContext().setAuthentication(authentication);
        String token = tokenProvider.createToken(authentication);
        final JwtUserDto jwtUserDto = (JwtUserDto) authentication.getPrincipal();
        // 保存在线信息
        onlineUserService.save(jwtUserDto, token, request);
        // 返回 token 与 用户信息
        Map<String, Object> authInfo = new HashMap<String, Object>(2) {{
            put("token", properties.getTokenStartWith() + token);
            put("user", jwtUserDto);
        }};
        if (loginProperties.isSingleLogin()) {
            //踢掉之前已经登录的token
            onlineUserService.checkLoginOnUser(authUser.getUserName(), token);
        }
        return BaseResponse.ok(authInfo);
    }
}
